package com.lele.ioc;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class BeanFactoryImpl implements BeanFactory{

    private Map<String,Object> beanMap = new HashMap();

    public BeanFactoryImpl(){
        try {
            // 创建输入流，读取 applicationContext.xml 文件里的内容
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream("applicationContext.xml");
            // 用工厂模式创建 Document 对象，也是为了读取 applicationContext.xml 文件里的内容
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            Document document = documentBuilder.parse(inputStream); // 把输入流放到 Document 对象中
            // 获取文件中所有的bean标签
            NodeList beanNodeList = document.getElementsByTagName("bean");
            for (int i = 0; i < beanNodeList.getLength(); i++) {
                Node beanNode = beanNodeList.item(i);
                if (beanNode.getNodeType() == Node.ELEMENT_NODE){ // 判断是否是元素节点
                    Element beanElement = (Element) beanNode; // 强转为 Element 类型
                    String beanId = beanElement.getAttribute("id"); // 拿 id 的值
                    String className = beanElement.getAttribute("class"); // 拿 class 的值
                    Object beanObj = Class.forName(className).newInstance(); // 利用反射创建 拿到的类 的实例
                    beanMap.put(beanId,beanObj); // 把 id 和 实例对象 放到map里
                }
            }
            // 组装bean之间的依赖关系
            for (int i = 0; i < beanNodeList.getLength(); i++) {
                Node beanNode = beanNodeList.item(i);
                if (beanNode.getNodeType() == Node.ELEMENT_NODE){ // 判断是否是元素节点
                    Element beanElement = (Element) beanNode; // 强转为 Element 类型
                    String beanId = beanElement.getAttribute("id"); // 拿 id 的值
                    NodeList beanChildNodeList = beanElement.getChildNodes(); // 拿bean里面的子节点
                    for (int j = 0; j < beanChildNodeList.getLength(); j++) { // 循坏子节点
                        Node beanChildNode = beanChildNodeList.item(j);
                        if (beanChildNode.getNodeType()==Node.ELEMENT_NODE && "property".equals(beanChildNode.getNodeName())){
                            Element propertyElement = (Element) beanChildNode; // 强转为 Element 类型
                            String propertyName = propertyElement.getAttribute("name"); // 拿 name 的值
                            String propertyRef = propertyElement.getAttribute("ref"); // 拿 ref 的值
                            Object refObj = beanMap.get(propertyRef); // 找到 propertyRef 对应的实例
                            Object beanObj = beanMap.get(beanId); // 找到 beanClass 对应的实例
                            // 将refObj设置到当前bean对应的实例的property属性上去
                            Class beanClazz = beanObj.getClass();
                            Field propertyField = beanClazz.getDeclaredField(propertyName); // 拿成员变量
                            propertyField.setAccessible(true);
                            propertyField.set(beanObj,refObj); // 给成员变量赋值，所有开始写了初始值=null
                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Object getBean(String id) {
        return beanMap.get(id);
    }
}
